<?php


namespace ke;


use app\common\http\exception\AppException;
use app\common\library\FormDataValidate;
use think\facade\Request;

trait KeAutoLogic
{

    /**
     * 自动化获取列表,默认含分页
     * @param array $options
     *              query 自定义查询
     *              with 预加载
     *              where 条件
     *              field 获取字段
     *              ignore_field 过滤字段
     *              order 排序
     *              group 分组
     *              limit
     *              paginate false时不会分页
     *              withBind 把预加载的参数赋值到顶级,默认会把预加载的参数隐藏掉
     *              hiddenWithBind true,绑定到顶级时是否隐藏自身
     * @return $this
     */
    public function autoList(array $options = [])
    {
        $query = new static;

        // 自定义query
        if (isset($options['query'])) {
            $query = call_user_func_array($options['query'], $query);
        } else {
            // 预加载
            if (isset($options['with'])) {
                $query = $query->with($options['with']);
            }
            // 条件
            if (isset($options['where'])) {
                $query = $query->where($options['where']);
            }
            // 字段
            if (isset($options['field'])) {
                $query = $query->field($options['field']);
            }
            // 字段过滤
            if (isset($options['ignore_field'])) {
                $query = $query->field($options['ignore_field'], true);
            }
            // 排序
            if (isset($options['order'])) {
                $query = $query->order($options['order']);
            }
            // 分组
            if (isset($options['group'])) {
                $query = $query->group($options['group']);
            }
            // limit
            if (isset($options['limit'])) {
                $query = $query->limit($options['limit']);
            }
        }

        // paginate=false时不分页
        if (isset($options['paginate']) && $options['paginate'] === false) {
            $res = $query->select();
        } else {
            $res = $query->paginate();
        }

        $hiddenWithBind = isset($options['hiddenWithBind']) ? ($options['hiddenWithBind']) : true;
        $res->each(function ($row) use($options, $hiddenWithBind) {
            // 绑定属性到父级
            if (isset($options['withBind'])) {
                foreach ($options['withBind'] as $name=>$bind) {
                    if (empty($options['with']) || !in_array($name, $options['with'])) {
                        continue;
                    }
                    foreach ($bind as $attr) {
                        $row[$name . '_' . $attr] = $row[$name][$attr];
                    }
                    if ($hiddenWithBind) unset($row[$name]);
                }
            }
        });

        return $res;
    }


    /**
     * 自动化获取详情
     * @param array $options
     * @return $this
     */
    public function autoRead(array $options = [])
    {
        $id = Request::get($this->getPk() . '/d');

        $query = new static;

        // 自定义query
        if (isset($options['query'])) {
            $query = call_user_func_array($options['query'], $query);
        } else {
            // 预加载
            if (isset($options['with'])) {
                $query = $query->with($options['with']);
            }
            // 条件
            if (isset($options['where'])) {
                $query = $query->where($options['where']);
            }
            // 字段
            if (isset($options['field'])) {
                $query = $query->field($options['field']);
            }
            // 字段过滤
            if (isset($options['ignore_field'])) {
                $query = $query->field($options['ignore_field'], true);
            }
            // 排序
            if (isset($options['order'])) {
                $query = $query->order($options['order']);
            }
        }
        $row = $query->findOrFail();

        $hiddenWithBind = isset($options['hiddenWithBind']) ? ($options['hiddenWithBind']) : true;

        // 绑定属性到父级
        if (isset($options['withBind'])) {
            foreach ($options['withBind'] as $name=>$bind) {
                if (empty($options['with']) || !in_array($name, $options['with'])) {
                    continue;
                }
                foreach ($bind as $attr) {
                    $row[$name . '_' . $attr] = $row[$name][$attr];
                }
                if ($hiddenWithBind) unset($row[$name]);
            }
        }
        return $row;
    }


    /**
     * 自动化创建 / 更新数据,传入的formdata有id时则为更新，没有则为新增
     * @param $validate
     * @param array $options
     * @return array ['type'=>'类型：insert创建，update更新', 'data'=>'创建/更新后的数据']
     */
    public function autoSave($validate, array $options = [])
    {
        $id = Request::post($this->getPk() . '/d');
        $form = new FormDataValidate($validate, $id ? 'edit' : 'add');

        if (isset($options['before'])) {
            call_user_func_array($options['before'], $form);
        }
        $response = [];
        if (isset($form[$this->getPk()])) {
            $data = static::where($this->getPk(), $form[$this->getPk()])
                ->where($options['where'] ?? null)
                ->findOrFail();
            $response['type'] = 'update';
            $response['data'] = $data;
        } else {
            $data = new static;
            $response['type'] = 'insert';
        }
        $data->save($form->toArray());
        if (isset($options['after'])) {
            $data = call_user_func_array($options['after'], $data);
        }
        $response['data'] = $data;

        return $response;
    }


    /**
     * 自动化删除
     * params id 整数型数组
     * @param array $options
     * @return bool
     */
    public function autoDelete(array $options = [])
    {
        $id = Request::post($this->getPk() . '/a', [], 'intval');
        if (empty($id)) {
            throw new AppException('删除失败:参数为空');
        }

        $res = static::where($this->getPk(), $id)->where($options['where'] ?? null)->delete();
        if (!$res) {
            throw new AppException('删除失败:数据库错误');
        }

        return true;
    }

}
